#include "connection_manager.h"

#include "tcp_socket.h"
#include "../core/null_deleter.h"

network::connection_manager::~connection_manager()
{
	_sender.clear();
	_queue->interrupt();

	typedef list<boost::shared_ptr<network::receiver> >::iterator it;
	for(it i = _receiver.begin(); i != _receiver.end(); ++i) {
		(*i)->interrupt();
		(*i).reset();
	}

	typedef list<boost::shared_ptr<network::connection_listener> >
			::iterator it2;
	for(it2 i = _listener.begin(); i != _listener.end(); ++i) {
		(*i)->interrupt();
		(*i).reset();
	}
	_receiver.clear();
	_listener.clear();
}

void network::connection_manager::add_recv(
				boost::shared_ptr<network::i_socket> sock,
				boost::shared_ptr<network::filetype> file)
{
	boost::mutex::scoped_lock l(_mutex);
	boost::shared_ptr<network::receiver> recv(network::receiver::create(
							sock, 
							_queue, 
							file));
	boost::shared_ptr<network::listener> list(this, core::null_deleter());
	recv->add_listener(list);
	_receiver.push_back(recv);
	_sender[sock] = file;
	recv->start_thread();
}

boost::shared_ptr<network::i_socket> network::connection_manager::add_listener(
								int port)
{
	boost::shared_ptr<network::tcp_socket> sock(new network::tcp_socket());
	sock->bind(port);
	boost::mutex::scoped_lock l(_mutex);
	boost::shared_ptr<network::connection_listener> list(new
		network::connection_listener(sock, _queue));
	_listener.push_back(list);
	list->start_thread();
	return sock;
}

boost::shared_ptr<network::sender> network::connection_manager::get_sender(
				boost::shared_ptr<network::i_socket> sock)
{
	boost::mutex::scoped_lock l(_mutex);
	return _sender[sock];
}

void network::connection_manager::notify(const network::notifier *n)
{
	boost::mutex::scoped_lock l(_mutex);
	// remove the listener
	typedef list<boost::shared_ptr<network::receiver> >::iterator it;
	it i = _receiver.begin();
	it next = _receiver.begin();
	while(i != _receiver.end()) {
		++next;
		if((*i).get() == n) {
			// hack!!11
			_sender.erase(boost::
				const_pointer_cast<network::i_socket>(
				(*i)->get_socket()));
			_receiver.erase(i);
		}
		i = next;
	}
}

